package com.brainhealth.customer.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.server.HttpServerRequest;
import com.alibaba.fastjson2.JSON;
import com.brainhealth.common.annotation.RepeatSubmit;
import com.brainhealth.common.constant.CacheConstants;
import com.brainhealth.common.constant.Constants;
import com.brainhealth.common.constant.NumberConstants;
import com.brainhealth.common.constant.ServiceExceptionStatus;
import com.brainhealth.common.core.redis.RedisCache;
import com.brainhealth.common.enums.*;
import com.brainhealth.common.exception.ServiceException;
import com.brainhealth.common.utils.*;
import com.brainhealth.customer.domain.*;
import com.brainhealth.customer.domain.vo.CustomerScheduleVO;
import com.brainhealth.customer.mapper.*;
import com.brainhealth.customer.service.ICustomerService;
import com.brainhealth.customer.service.ICustomerExerciseService;
import com.brainhealth.customer.service.IScoreRecordService;
import com.brainhealth.customer.service.ISysLoginPushService;
import com.brainhealth.system.domain.vo.ScheduleVo;
import com.brainhealth.utils.CommonUtils;
import com.brainhealth.utils.FillBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

import static com.brainhealth.common.constant.Constants.DEFAULT_LINK;

/**
 * 会员信息Service业务层处理
 * 
 * @author wolong
 * @date 2023-04-27
 */
@Service
public class CustomerServiceImpl implements ICustomerService 
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private CustomerLevelMapper customerLevelMapper;
    @Autowired
    private CustomerExerciseMapper customerExerciseMapper;
    @Autowired
    private ExerciseProductMapper exerciseProductMapper;
    @Autowired
    private ExerciseOrderMapper exerciseOrderMapper;
    @Autowired
    private ExerciseMapper exerciseMapper;
    @Autowired
    ISysLoginPushService sysLoginPushService;
    @Autowired
    ChatMainMapper chatMainMapper;
    @Autowired
    IScoreRecordService scoreRecordService;

    @Autowired
    private ICustomerExerciseService customerExerciseService;

    /**
     * 查询会员信息
     * 
     * @param customerId 会员信息主键
     * @return 会员信息
     */
    @Override
    public Customer selectCustomerByCustomerId(Long customerId)
    {
        return customerMapper.selectCustomerByCustomerId(customerId);
    }

    @Override
    public List<Customer> selectCustomerByCustomerIds(List<Long> customerIds) {
        return customerMapper.selectCustomerByCustomerIds(customerIds);
    }

    /**
     * 查询会员信息列表
     * 
     * @param customer 会员信息
     * @return 会员信息
     */
    @Override
    public List<Customer> selectCustomerList(Customer customer)
    {
        return customerMapper.selectCustomerList(customer);
    }

    @Override
    public List<Customer> selectCustomerOrderList(BuriedPointQuery buriedPointQuery)
    {
        try
        {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date bDate = sdf.parse(buriedPointQuery.getStartTime());
            Date eDate = sdf.parse(buriedPointQuery.getEndTime());
            Date updateStartTime = sdf.parse(buriedPointQuery.getUpdateStartTime());
            Date updateEndTime = sdf.parse(buriedPointQuery.getUpdateEndTime());
            return customerMapper.selectCustomerOrderList(buriedPointQuery.getOrgNo(), bDate, eDate,updateStartTime,updateEndTime);
        } catch (Exception e)
        {
            logger.error("转换日期异常", e);
        }
        return null;
    }

    /**
     * 新增会员信息
     * 
     * @param customer 会员信息
     * @return 结果
     */
    @Override
    public int insertCustomer(Customer customer)
    {
        Customer queryCustomer = customerMapper.selectCustomerByPhone(customer.getPhone());
        if (queryCustomer != null)
        {
            throw new RuntimeException("用户已存在");
        }
        customer.setCreateTime(DateUtils.getNowDate());
        return customerMapper.insertCustomer(customer);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int addWhiteListCustomer(String phone)
    {
        int result;
        Customer queryCustomer = customerMapper.selectCustomerByPhone(phone);
        if (queryCustomer != null)
        {
            queryCustomer.setMechanismId(0l);
            result = customerMapper.updateCustomer(queryCustomer);
            if (result > 0)
            {
                return result;
            }
        } else
        {
            Customer customer = addCustomerAndExerciseList("",phone, 0l, 1l, PayType.OtherPay);
            if (customer != null)
            {
                result = 1;
            }else
            {
                result = 0;
            }
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addExperienceCustomer(String inviteCustomerId,String phone, String smsCode)
    {
        String redisSmsCode = redisCache.getCacheObject(CacheConstants.SMS_CODE + phone);
        if (StringUtils.isEmpty(redisSmsCode) || !redisSmsCode.equals(smsCode))
        {
            throw new ServiceException("验证码不正确或已失效", ServiceExceptionStatus.CODE_ERROR);
        }
        Customer queryCustomer = customerMapper.selectCustomerByPhone(phone);
        if (queryCustomer != null)
        {
            throw new ServiceException("本用户已经体验过训练产品请从公众号登录！", ServiceExceptionStatus.USER_EXIST);
        } else
        {
            Customer customer = addCustomerAndExerciseList(inviteCustomerId,phone, -1l, 2l, PayType.Experience5);
            if (customer != null)
            {
                CustomerLevel customerLevel = customerLevelMapper.selectCustomerLevelByCustomerLevelId(customer.getCustomerLevelId());
                customer.setCustomerLevel(customerLevel);
                long ts = DateUtils.getTimeMillis();
                String token = refreshToken(ts,customer);
                return token;
            }
        }
        return "";
    }

    @Override
    public boolean initExperience(String phone)
    {
        deleteCustomerToken(phone);
        Customer customer = customerMapper.selectCustomerByPhone(phone);
        Exercise query = new Exercise();
        query.setExerciseProductId(2L);
        List<Exercise> lstExercise = exerciseMapper.selectExerciseList(query);
        ExerciseOrder queryOrder = new ExerciseOrder();
        queryOrder.setCustomerId(customer.getCustomerId());
        List<ExerciseOrder> lstExperience = exerciseOrderMapper.selectExerciseOrderList(queryOrder);
        for (ExerciseOrder order :lstExperience)
        {
            if (order.getPayType() == PayType.Experience5)
            {
                exerciseOrderMapper.deleteExerciseOrderByExerciseOrderId(order.getExerciseOrderId());
            }
            if (order.getStatus() == PayStatus.Exercise)
            {
                order.setStatus(PayStatus.Finish);
            }
        }
        for (Exercise exercise : lstExercise)
        {
            customerExerciseMapper.deleteCustomerExerciseByCustomerId(customer.getCustomerId(), exercise.getExerciseId());
        }
        customer.setMechanismId(-1L);
        int result = customerMapper.updateCustomer(customer);
        if (result > 0)
        {
            ExerciseProduct exerciseProduct = exerciseProductMapper.selectExerciseProductByExerciseProductId(2L);
            ExerciseOrder exerciseOrder = new ExerciseOrder();
            exerciseOrder.setPayAmount(exerciseProduct.getPrice());
            exerciseOrder.setAmount(exerciseProduct.getPrice());
            exerciseOrder.setCustomerId(customer.getCustomerId());
            exerciseOrder.setCustomerName(customer.getNickName());
            exerciseOrder.setCustomerPhone(customer.getPhone());
            exerciseOrder.setCycle(exerciseProduct.getCycle());
            exerciseOrder.setExerciseDesc(exerciseProduct.getDescription());
            exerciseOrder.setExerciseName(exerciseProduct.getName());
            exerciseOrder.setExerciseProductId(exerciseProduct.getExerciseProductId());
            exerciseOrder.setCreateTime(new Date());
            exerciseOrder.setPayType(PayType.Experience5);
            exerciseOrder.setStatus(PayStatus.Exercise);
            exerciseOrder.setOrderId(SnowFlakeUtil.getDefaultSnowFlakeId().toString());
            exerciseOrderMapper.insertExerciseOrder(exerciseOrder);
            List<CustomerExercise> lstCustomerExercise = FillBeanUtils.fillCustomerExerciseList(exerciseProduct, exerciseOrder);
            customerExerciseMapper.batchInsertCustomerExercise(lstCustomerExercise);
            return true;
        }
        return false;
    }

    @Override
    public void resetExperienceCustomer()
    {
        long ts = DateUtils.getTimeMillis();
        List<Customer> lstCustomer = customerMapper.selectExperienceCustomerList();
        logger.info("ts:{}，超时120小时过期用户结果：{}", ts, JSON.toJSONString(lstCustomer.stream().map(Customer::getCustomerId).collect(Collectors.toList())));
        for (Customer customer: lstCustomer)
        {
            ExerciseOrder queryOrder = new ExerciseOrder();
            queryOrder.setCustomerId(customer.getCustomerId());
            queryOrder.setStatus(PayStatus.Exercise);
            List<ExerciseOrder> exerciseOrders = exerciseOrderMapper.selectExerciseOrderList(queryOrder);
            if (exerciseOrders.size() > 0)
            {
                ExerciseOrder order = exerciseOrders.get(0);
                logger.info("ts:{}，超时120小时过期用户订单：{}", ts, JSON.toJSONString(order));
                order.setStatus(PayStatus.Finish);
                exerciseOrderMapper.updateExerciseOrder(order);
                CustomerExercise queryExercise = new CustomerExercise();
                queryExercise.setOrderId(order.getOrderId());
                List<CustomerExercise> lstExercise = customerExerciseMapper.selectCustomerExerciseList(queryExercise);
                for (CustomerExercise exercise : lstExercise)
                {
                    if (exercise.getStatus() == CustomerExerciseStatus.NoFinish || exercise.getStatus() == CustomerExerciseStatus.NoOpen)
                    {
                        exercise.setStatus(CustomerExerciseStatus.expired);
                        exercise.setOpenTime(new Date());
                    }
                }
                customerExerciseMapper.updateBatch(lstExercise);
                deleteCustomerToken(customer.getPhone());
            }
        }
    }

    /**
     * 添加会员信息和会员训练记录
     * @param inviteCustomerId 邀请人ID
     * @param phone 手机号
     * @param userType 用户类型
     * @param productId 产品ID
     * @param payType 支付类型
     * @return
     */
    public Customer addCustomerAndExerciseList(String inviteCustomerId,String phone, Long userType, Long productId, PayType payType)
    {
        Customer customer = FillBeanUtils.fillCustomerInfo(phone);
        customer.setMechanismId(userType);
        int result = customerMapper.insertCustomer(customer);
        if (result > 0)
        {
            ExerciseProduct exerciseProduct = exerciseProductMapper.selectExerciseProductByExerciseProductId(productId);
            ExerciseOrder exerciseOrder = new ExerciseOrder();
            exerciseOrder.setPayAmount(exerciseProduct.getPrice());
            exerciseOrder.setAmount(exerciseProduct.getPrice());
            exerciseOrder.setCustomerId(customer.getCustomerId());
            exerciseOrder.setCustomerName(customer.getNickName());
            exerciseOrder.setCustomerPhone(customer.getPhone());
            exerciseOrder.setCycle(exerciseProduct.getCycle());
            exerciseOrder.setExerciseDesc(exerciseProduct.getDescription());
            exerciseOrder.setExerciseName(exerciseProduct.getName());
            exerciseOrder.setExerciseProductId(exerciseProduct.getExerciseProductId());
            exerciseOrder.setCreateTime(new Date());
            exerciseOrder.setPayType(payType);
            exerciseOrder.setStatus(PayStatus.Exercise);
            exerciseOrder.setOrderId(SnowFlakeUtil.getDefaultSnowFlakeId().toString());
            exerciseOrderMapper.insertExerciseOrder(exerciseOrder);
            List<CustomerExercise> lstCustomerExercise = FillBeanUtils.fillCustomerExerciseList(exerciseProduct, exerciseOrder);
            customerExerciseMapper.batchInsertCustomerExercise(lstCustomerExercise);

            if (StringUtils.isNotBlank(inviteCustomerId)) {
                ScoreRecord scoreRecord = constructScoreRecord(inviteCustomerId, customer.getCustomerId(), exerciseOrder.getOrderId());
                int insertResult = scoreRecordService.insertScoreRecord(scoreRecord);
                logger.info("邀请人{}新增积分结果{}", scoreRecord.getCustomerId(), insertResult);
                Customer inviteCustomer = customerMapper.selectCustomerByCustomerId(scoreRecord.getCustomerId());
                if (null != inviteCustomer) {
                    Long score = inviteCustomer.getScore();
                    score = null == score ? Long.valueOf(NumberConstants.ZERO) : score;
                    score = score + scoreRecord.getScore();
                    inviteCustomer.setScore(score);
                    int updateResult = customerMapper.updateCustomer(inviteCustomer);
                    logger.info("邀请人{}更新积分结果{}", scoreRecord.getCustomerId(), updateResult);
                }
            }

            return customer;
        }
        return null;
    }

    private ScoreRecord constructScoreRecord(String inviteCustomerId,Long userId,String orderNo) {
        ScoreRecord scoreRecord = new ScoreRecord();
        //TODO 提交代码时替换
        Long customerId =  Long.valueOf(AesUtils.decryptHex(inviteCustomerId));
        //Long customerId = Long.valueOf(NumberConstants.SIX);
        String strCustomerId = null == userId ? "" : String.valueOf(userId);
        Date now = DateUtils.getNowDate();
        Integer maxRecordId = scoreRecordService.getMaxRecordId();
        maxRecordId = null==maxRecordId?NumberConstants.ONE:maxRecordId+1;
        scoreRecord.setRecordId(Long.valueOf(maxRecordId));
        scoreRecord.setCustomerId(customerId);
        scoreRecord.setOrderNo(orderNo);
        scoreRecord.setCountSort(null);
        scoreRecord.setScoreType(ScoreTypeEnum.INVITED.getCode());
        scoreRecord.setScore(Long.valueOf(ScoreTypeEnum.INVITED.getScore()));
        scoreRecord.setScoreDesc(ScoreTypeEnum.INVITED.getInfo());
        scoreRecord.setYn(YNEnum.NO.getCode());
        scoreRecord.setCreateUser(strCustomerId);
        scoreRecord.setCreateTime(now);
        scoreRecord.setUpdateUser(strCustomerId);
        scoreRecord.setUpdateTime(now);

        return scoreRecord;
    }


    /**
     * 修改会员信息
     * 
     * @param customer 会员信息
     * @return 结果
     */
    @Override
    public int updateCustomer(Customer customer)
    {
        customer.setUpdateTime(DateUtils.getNowDate());
        return customerMapper.updateCustomer(customer);
    }

    @Override
    public int initNomalCustomer(Long customerId)
    {
        int result = customerMapper.initNomalCustomer(customerId);
        return result;
    }

    @Override
    public boolean addCustomerBlack(Customer customer)
    {
        if (customer.getIsBlack().equals(UserStatus.OK.getCode()))
        {
            customer.setIsBlack(UserStatus.DISABLE.getCode());
        } else
        {
            customer.setIsBlack(UserStatus.OK.getCode());
        }
        return this.updateCustomerInfo(customer);
    }

    @Override
    public boolean modifyCustomerPhone(String oldPhone, String newPhone)
    {
        Customer customer = customerMapper.selectCustomerByPhone(oldPhone);
        customer.setPhone(newPhone);
        customer.setOpenId("");
        boolean result = updateCustomerInfo(customer);
        if (result)
        {
            return true;
        }
        return false;
    }

    /**
     * 批量删除会员信息
     * 
     * @param customerIds 需要删除的会员信息主键
     * @return 结果
     */
    @Override
    public int deleteCustomerByCustomerIds(Long[] customerIds)
    {
        return customerMapper.deleteCustomerByCustomerIds(customerIds);
    }

    /**
     * 删除会员信息信息
     * 
     * @param customerId 会员信息主键
     * @return 结果
     */
    @Override
    public int deleteCustomerByCustomerId(Long customerId)
    {
        return customerMapper.deleteCustomerByCustomerId(customerId);
    }

    @Override
    public boolean SendSmsCodeTest(String phone)
    {
        try
        {
            if (redisCache.hasKey(CacheConstants.SMS_CODE + phone))
            {
                throw new RuntimeException("提示：不能重复发送");
            }
            StringBuilder randomCode = new StringBuilder();
            while (randomCode.length() < 4)
            {
                String randomNumber = String.valueOf(RandomUtil.randomInt(1, 9));
                randomCode.append(randomNumber);
            }
            randomCode.setLength(0);
            randomCode.append("1234");
            redisCache.setCacheObject(CacheConstants.SMS_CODE + phone, randomCode, 60 * 3, TimeUnit.SECONDS);
            return true;
        } catch (Exception e)
        {
            logger.error(e.getMessage());
            return false;
        }
    }

    @Override
    public boolean SendSmsCode(String phone)
    {
        try
        {
            if (redisCache.hasKey(CacheConstants.SMS_CODE + phone))
            {
                throw new RuntimeException("提示：不能重复发送");
            }
            StringBuilder randomCode = new StringBuilder();
            while (randomCode.length() < 4)
            {
                String randomNumber = String.valueOf(RandomUtil.randomInt(1, 9));
                randomCode.append(randomNumber);
            }
            logger.info("手机号" + phone + "验证码" + randomCode);
            boolean result = SmsUtils.sendAliyunSms(phone, randomCode.toString());
            if (result)
            {
                logger.info("发送阿里云短信验证码成功！");
                //todo 使用临时固定验证码来测试代码
                redisCache.setCacheObject(CacheConstants.SMS_CODE + phone, randomCode, 60 * 3, TimeUnit.SECONDS);
                return true;
            }
        } catch (Exception e)
        {
            logger.error(e.getMessage());
            return false;
        }
        return false;
    }

    @Override
    public String customerLogin(String phone, String smsCode)
    {
        String redisSmsCode = redisCache.getCacheObject(CacheConstants.SMS_CODE + phone);
        if (StringUtils.isEmpty(redisSmsCode) || !redisSmsCode.equals(smsCode))
        {
            throw new ServiceException("验证码不正确或已失效", ServiceExceptionStatus.CODE_ERROR);
        }
        Customer customer = customerMapper.selectCustomerByPhone(phone);
        if (customer == null)
        {
            throw new ServiceException("会员信息不存在！", ServiceExceptionStatus.USER_EXIST);
        }
        if (customer.getIsBlack().equals(UserStatus.DISABLE.getCode()))
        {
            throw new ServiceException("会员属于黑名单无法登录！", ServiceExceptionStatus.BLACK_USER);
        }
        ExerciseOrder query = new ExerciseOrder();
        query.setCustomerId(customer.getCustomerId());
        List<ExerciseOrder> lstOrder = exerciseOrderMapper.selectExerciseOrderList(query);
        //如果是体验用户超过120小时没有付费订单则不允许登录
        if (customer.getMechanismId() != null && customer.getMechanismId().equals(-1L))
        {
            Long t = DateUtils.addHours(customer.getCreateTime(), 120).getTime() - new Date().getTime();
            ExerciseOrder payOrder = lstOrder.stream().filter(item -> item.getStatus() == PayStatus.Paid).findFirst().orElse(null);
            ExerciseOrder finishOrder = lstOrder.stream().filter(item -> item.getPayType() == PayType.Experience5).findFirst().orElse(null);
            if (finishOrder != null && finishOrder.getStatus() == PayStatus.Finish && payOrder == null && t < 0)
            {
                throw new ServiceException("您的训练营体验已结束无法登录，您尽快去付费！", ServiceExceptionStatus.EXPERIENCE_EXPIRE);
            }
        }
        //如果是普通用户但没有付费也不允许登录
        if (customer.getMechanismId() == null)
        {
            ExerciseOrder payOrder = lstOrder.stream().filter(item -> item.getStatus() == PayStatus.Paid).findFirst().orElse(null);
            ExerciseOrder exerciseOrder = lstOrder.stream().filter(item -> item.getStatus() == PayStatus.Exercise).findFirst().orElse(null);
            if (payOrder == null && exerciseOrder == null)
            {
                throw new ServiceException("您的训练营体验已结束无法登录，您尽快去付费！", ServiceExceptionStatus.EXPERIENCE_EXPIRE);
            }
        }
        customer.setLoginTime(new Date());
        customerMapper.updateCustomer(customer);
        CustomerLevel customerLevel = customerLevelMapper.selectCustomerLevelByCustomerLevelId(customer.getCustomerLevelId());
        customer.setCustomerLevel(customerLevel);
        clearPushTask(String.valueOf(customer.getPhone()));
        return refreshCustomerToken(customer);
    }

    /**
     *
     * 用户表
     * SELECT * FROM customer WHERE phone='18516800306'; -- 6
     * 训练表
     * SELECT * FROM customer_exercise WHERE customer_id=6;
     * 订单表
     * SELECT * FROM exercise_order WHERE customer_id=6;
     * 聊天主表
     * SELECT * FROM chat_main WHERE customer_id=6;
     *
     */
    @Override
    public Integer initCustomer(InitUserParam initUserParam) {
        long ts = DateUtils.getTimeMillis();
        try {
            Date now = DateUtils.getNowDate();
            //1、校验手机号
            //2、添加日志

            logger.info("ts:{}，初始化用户开始，入参：{}========================================================================", ts, initUserParam);
            //1、初始化用户表
            Customer customer = customerMapper.selectCustomerByPhone(initUserParam.getPhone());
            customer.setCountSort(initUserParam.getCourseNo());
            int updateCustomerResult = customerMapper.updateCustomer(customer);
            logger.info("ts:{}，初始化用户表结果：{}", ts, updateCustomerResult);
            //2、初始化训练表
            int updateCustomerExerciseResult = 0;
            Long courseNo = initUserParam.getCourseNo();
            String orderNo = initUserParam.getOrderNo();
            CustomerExercise customerExercise = new CustomerExercise();
            customerExercise.setCustomerId(customer.getCustomerId());
            customerExercise.setCountSort(courseNo);
            customerExercise.setOrderId(orderNo);
            List<CustomerExercise> customerExerciseList = customerExerciseMapper.selectCustomerExerciseList(customerExercise);
            if (!CollectionUtils.isEmpty(customerExerciseList)) {
                for (CustomerExercise exercise : customerExerciseList) {
                    exercise.setStatus(CustomerExerciseStatus.NoFinish);
                    exercise.setOpenTime(now);
                    exercise.setStartTime(null);
                    exercise.setEndTime(null);
                }
                updateCustomerExerciseResult = customerExerciseMapper.updateBatch(customerExerciseList);
            }
            logger.info("ts:{}，初始化训练表结果：{}", ts, updateCustomerExerciseResult);
            int updateCustomerExerciseResult2 = 0;
            List<Long> courseNoList = getCourseNoList(Long.valueOf(NumberConstants.TWENTY_EIGHT), courseNo);
            customerExercise = new CustomerExercise();
            customerExercise.setCountSortList(courseNoList);
            customerExercise.setOrderId(orderNo);
            customerExerciseList = customerExerciseMapper.selectCustomerExerciseList(customerExercise);
            if (!CollectionUtils.isEmpty(customerExerciseList)) {
                for (CustomerExercise exercise : customerExerciseList) {
                    exercise.setStatus(CustomerExerciseStatus.NoOpen);
                    exercise.setOpenTime(null);
                    exercise.setStartTime(null);
                    exercise.setEndTime(null);
                }
                updateCustomerExerciseResult2 = customerExerciseMapper.updateBatch(customerExerciseList);
            }
            logger.info("ts:{}，初始化训练表结果：{}", ts, updateCustomerExerciseResult2);
            //3.初始化订单表
            ExerciseOrder exerciseOrder = new ExerciseOrder();
            exerciseOrder.setCustomerId(customer.getCustomerId());
            exerciseOrder.setOrderId(initUserParam.getOrderNo());
            List<ExerciseOrder> exerciseOrderList = exerciseOrderMapper.selectExerciseOrderList(exerciseOrder);
            if (!CollectionUtils.isEmpty(exerciseOrderList) && exerciseOrderList.size() > 0) {
                exerciseOrder = exerciseOrderList.get(0);
                if (!exerciseOrder.getStatus().equals(PayStatus.Exercise)) {
                    exerciseOrder.setStatus(PayStatus.Exercise);
                    int updateExerciseOrderResult = exerciseOrderMapper.updateExerciseOrder(exerciseOrder);
                    logger.info("ts:{}，初始化订单表结果：{}", ts, updateExerciseOrderResult);
                }
            }
            //4.初始化聊天主表
            ChatMain chatMain = new ChatMain();
            chatMain.setCustomerId(customer.getCustomerId());
            List<ChatMain> chatMainList = chatMainMapper.selectChatMainList(chatMain);
            if (!CollectionUtils.isEmpty(chatMainList)) {
                List<Long> mainIdList = chatMainList.stream().map(item -> item.getId()).collect(Collectors.toList());
                Long[] mainIdArr = mainIdList.toArray(new Long[mainIdList.size()]);
                int deleteChatMainResult = chatMainMapper.deleteChatMainByIds(mainIdArr);
                logger.info("ts:{}，初始化聊天主表结果：{}", ts, deleteChatMainResult);
            }
            logger.info("ts:{}，初始化用户结束========================================================================", ts);
            refreshCustomerToken(customer);
            return NumberConstants.ONE;
        } catch (Exception e) {
            logger.error("ts:{}，初始化用户异常", ts, e);
            return null;
        }
    }

    private List<Long> getCourseNoList(Long maxCourseNo,Long currentCourseNo)
    {
        if (maxCourseNo.equals(currentCourseNo)){
            return null;
        }
        List<Long> courseNoList = new ArrayList<>();
        long nextCourseNo =  currentCourseNo+1;
        for (Long i = nextCourseNo; i <= maxCourseNo; i++) {
            courseNoList.add(i);
        }
        return courseNoList;
    }

    @Override
    public boolean customerLoginOut(HttpServletRequest request)
    {
        String token = request.getHeader("tokens");
        if (StringUtils.isEmpty(token))
        {
            throw new RuntimeException("token不能为空");
        }
        Collection<String> collection = redisCache.keys(CacheConstants.CUSTOMER_TOKEN + "*" + ":" + token);
        if (collection.size() > 0)
        {
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
            }
            boolean result = redisCache.deleteObject(tokenKey);
            if (result)
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 清除推送任务
     * @param userId
     */
    public void clearPushTask(String userId) {
        try {
            List<SysLoginPush> sysLoginPushList = sysLoginPushService.selectSysLoginPushList(null);
            if (CollectionUtils.isEmpty(sysLoginPushList)) {
                return;
            }
            for (SysLoginPush sysLoginPush : sysLoginPushList) {
                Long taskId = sysLoginPush.getTaskId();
                String cacheKey = String.format("%s:%s:%s", CacheConstants.PUSH_LOGIN_KEY, taskId, userId);
                Object cacheObject = redisCache.getCacheObject(cacheKey);
                if (null != cacheObject) {
                    logger.info("用户ID：{} 清除消息推送缓存，开始", userId);
                    redisCache.deleteObject(cacheKey);
                    logger.info("用户ID：{} cacheKey：{} 清除消息推送缓存，结束", userId, cacheKey);
                }
            }
        } catch (Exception e) {
            logger.error("清除推送任务缓存失败：", e);
        }
    }

    @Override
    public String customerRegister(String ip, String phone, String smsCode, String mechanismId)
    {
        String redisSmsCode = redisCache.getCacheObject(CacheConstants.SMS_CODE + phone);
        if (StringUtils.isEmpty(redisSmsCode) || !redisSmsCode.equals(smsCode))
        {
            throw new ServiceException("验证码不正确或已失效", ServiceExceptionStatus.CODE_ERROR);
        }
        String token = "";
        Customer queryCustomer = customerMapper.selectCustomerByPhone(phone);
        if (queryCustomer != null)
        {
            CustomerLevel customerLevel = customerLevelMapper.selectCustomerLevelByCustomerLevelId(queryCustomer.getCustomerLevelId());
            queryCustomer.setCustomerLevel(customerLevel);
            token = refreshCustomerToken(queryCustomer);
        }
        if (queryCustomer == null)
        {
            Customer customer = FillBeanUtils.fillCustomerInfo(phone);
            customer.setIpAddress(ip);
            if (!StringUtils.isNullOrEmpty(mechanismId))
            {
                Long mechanismInfo = Long.valueOf(AesUtils.decryptHex(mechanismId));
                customer.setMechanismId(mechanismInfo);
            }
            int result = customerMapper.insertCustomer(customer);
            if (result > 0)
            {
                CustomerLevel customerLevel = customerLevelMapper.selectCustomerLevelByCustomerLevelId(customer.getCustomerLevelId());
                customer.setCustomerLevel(customerLevel);
                token = refreshCustomerToken(customer);
                return token;
            }
        }
        return token;
    }

    @Override
    public boolean updateCustomerInfo(Customer customer)
    {
        int result = updateCustomer(customer);
        if (result > 0)
        {
            refreshCacheCustomer(customer);
            return true;
        }
        return false;
    }

    @Override
    public Customer getCustomerInfo(HttpServletRequest request)
    {
        Customer cacheCustomer = CommonUtils.getCustomerByRequest(request);
        Customer customer = selectCustomerByCustomerId(cacheCustomer.getCustomerId());
        if (customer.getCustomerLevel() == null)
        {
            CustomerLevel customerLevel = customerLevelMapper.selectCustomerLevelByCustomerLevelId(customer.getCustomerLevelId());
            customer.setCustomerLevel(customerLevel);
        }
        refreshCacheCustomer(customer);
        return customer;
    }

    /**
     * 会员信息签到
     * @param request
     * @return
     */
    @Override
    public boolean customerSignIn(HttpServletRequest request)
    {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        logger.info("会员签到，会员ID{}，签到时间{}，当前训练次数{}", customer.getCustomerId(), new Date(), customer.getCountSort());
        Object sortCount = redisCache.getCacheObject(CacheConstants.CUSTOMER_SIGN + customer.getPhone());
        if (StringUtils.isNull(sortCount) || !sortCount.toString().equals(customer.getCountSort().toString()))
        {
            customer.setLevelValue(customer.getLevelValue() + 3);
            this.updateCustomerInfo(customer);
            redisCache.setCacheObject(CacheConstants.CUSTOMER_SIGN + customer.getPhone(), customer.getCountSort().toString());
            return true;
        }
        return false;
    }

    /**
     * 获取会员日程信息
     * @param request
     * @return
     */
    @Override
    public CustomerScheduleVO getCustomerScheduleInfo(HttpServletRequest request)
    {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        CustomerLevel customerLevel = customerLevelMapper.selectCustomerLevelByCustomerLevelId(customer.getCustomerLevelId());
        NowCustomerExercise nowCustomerExercise = customerExerciseService.getNowCustomerExerciseList(customer);
        Map<Long, List<CustomerExercise>> mCustomerExercise = CommonUtils.getCountSortMap(nowCustomerExercise.getLstCustomerExercise());
        //前端首页显示内容对象填充
        CustomerScheduleVO customerScheduleVo = new CustomerScheduleVO();
        int remainCount = 1;
        int finishCount = 0;
        int nowTime = 0;
        int finishTime = 0;
        for (Map.Entry<Long, List<CustomerExercise>> entry : mCustomerExercise.entrySet())
        {
            for (CustomerExercise exercise : entry.getValue())
            {
                if (exercise.getExerciseTime() != null)
                {
                    finishTime += exercise.getExerciseTime();
                }
                if (exercise.getStatus() == CustomerExerciseStatus.Finished)
                {
                    finishCount++;
                }
            }
            if (entry.getValue().get(0).getStatus() == CustomerExerciseStatus.NoOpen)
            {
                remainCount++;
            }
            List<CustomerExercise> lstDayExercise = entry.getValue();
            ScheduleVo scheduleVo = new ScheduleVo();
            CustomerExercise customerExercise = lstDayExercise.stream().filter(item -> item.getStatus() == CustomerExerciseStatus.NoFinish).findFirst().orElse(null);
            if (customerExercise == null)
            {
                CustomerExercise tmpData = lstDayExercise.get(lstDayExercise.size() - 1);
                if (tmpData.getStatus() != CustomerExerciseStatus.NoOpen)
                {
                    if ((tmpData.getCountSort() % nowCustomerExercise.getOrder().getCycle()) == 0)
                    {
                        remainCount = 0;
                    }
                }
            }
            //判断今次的训练状态
            boolean finish = false;
            for (CustomerExercise tmpData : lstDayExercise)
            {
                if (tmpData.getStatus() == CustomerExerciseStatus.Finished)
                {
                    finish = true;
                }
            }
            if (customerExercise != null)
            {
                scheduleVo.setCountSort(customerExercise.getCountSort());
                scheduleVo.setCustomerExerciseStatus(CustomerExerciseStatus.Now);
                scheduleVo.setExerciseStatus(CustomerExerciseStatus.Now.getInfo());
                customerScheduleVo.getLstSchedule().add(scheduleVo);
                for (CustomerExercise exercise : entry.getValue())
                {
                    if (exercise.getExerciseTime() != null)
                    {
                        nowTime += exercise.getExerciseTime();
                    }
                }
                if (finish == false)
                {
                    List<CustomerExercise> lstPreExercise = mCustomerExercise.get(customerExercise.getCountSort() - 1);
                    if (lstPreExercise != null)
                    {
                        for (CustomerExercise exercise : lstPreExercise)
                        {
                            if (exercise.getExerciseTime() != null)
                            {
                                nowTime += exercise.getExerciseTime();
                            }
                        }
                    }
                }
                continue;
            }
            scheduleVo.setCustomerExerciseStatus(entry.getValue().get(0).getStatus());
            scheduleVo.setExerciseStatus(entry.getValue().get(0).getStatus().getInfo());
            scheduleVo.setCountSort(entry.getValue().get(0).getCountSort());
            CustomerExercise expiredExercise = lstDayExercise.stream().filter(item -> item.getStatus() == CustomerExerciseStatus.expired).findFirst().orElse(null);
            CustomerExercise finishExercise = lstDayExercise.stream().filter(item -> item.getStatus() == CustomerExerciseStatus.Finished).findFirst().orElse(null);
            if (expiredExercise != null && finishExercise != null)
            {
                scheduleVo.setCustomerExerciseStatus(CustomerExerciseStatus.NoFinish);
                scheduleVo.setExerciseStatus(CustomerExerciseStatus.NoFinish.getInfo());
            }
            customerScheduleVo.getLstSchedule().add(scheduleVo);
        }
        customerScheduleVo.setHasPayOrder(false);
        ExerciseOrder payOrder = new ExerciseOrder();
        payOrder.setStatus(PayStatus.Paid);
        payOrder.setCustomerId(customer.getCustomerId());
        List<ExerciseOrder> lstPayOrder = exerciseOrderMapper.selectExerciseOrderList(payOrder);
        if (lstPayOrder.size() > 0)
        {
            customerScheduleVo.setHasPayOrder(true);
            for (ExerciseOrder order : lstPayOrder)
            {
                remainCount += order.getCycle();
            }
        }
        customerScheduleVo.setExerciseRemain(remainCount);
        customerScheduleVo.setRemainTips("您的付费课程剩余" + remainCount + "次。");
        if (remainCount <= 10)
        {
            customerScheduleVo.setRemainTips("您的付费课程剩余" + remainCount + "次为保证您的训练治疗请及时续费。");
        }
        if (customer.getMechanismId() != null && customer.getMechanismId().equals(-1L))
        {
            Long t = DateUtils.addHours(customer.getCreateTime(), 120).getTime() - new Date().getTime();
            if (t > 0)
            {
                customerScheduleVo.setRemainTime(DateUtils.timeDistance(DateUtils.addHours(customer.getCreateTime(), 120), new Date()));
            } else
            {
                customerScheduleVo.setRemainTime("体验用户已过期！");
            }
        }
        //如果是最后一节课则获取最后一节课的训练时间
        if (nowTime == 0)
        {
            for (CustomerExercise exercise : mCustomerExercise.get(customer.getCountSort()))
            {
                if (exercise.getExerciseTime() != null)
                {
                    nowTime += exercise.getExerciseTime();
                }
            }
        }
        customerScheduleVo.setExerciseCount(finishCount);
        customerScheduleVo.setExerciseTime(finishTime);
        customerScheduleVo.setExerciseNowTime(nowTime);
        customerScheduleVo.setCustomerName(customer.getCustomerName());
        customerScheduleVo.setLevelIconUrl(customerLevel.getIcon());
        return customerScheduleVo;
    }

    @Override
    public String createCustomerShareLink(HttpServletRequest request)
    {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        String aesCustomerId = AesUtils.encryptHex(customer.getCustomerId().toString());
        return DEFAULT_LINK + aesCustomerId;
    }

    /**
     * 刷新会员token信息
     * @param customer
     * @return
     */
    @Override
    public String refreshCustomerToken(Customer customer)
    {
        deleteCustomerToken(customer.getPhone());
        String token = UUID.randomUUID().toString();
        redisCache.setCacheObject(CacheConstants.CUSTOMER_TOKEN + customer.getPhone() + ":" + token, JSON.toJSONString(customer), 3, TimeUnit.DAYS);
        return token;
    }


    @Override
    public String refreshToken(Long ts,Customer customer)
    {
        Collection<String> collection = redisCache.keys(CacheConstants.CUSTOMER_TOKEN + customer.getPhone() + "*");
        if (collection.size()>0){
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
                redisCache.setCacheObject(tokenKey, JSON.toJSONString(customer), 3, TimeUnit.DAYS);
                logger.info("ts:{} 设置token缓存 key:{} value:{}",ts,tokenKey,customer);
                return tokenKey;
            }
        }
        String token = UUID.randomUUID().toString();
        redisCache.setCacheObject(CacheConstants.CUSTOMER_TOKEN + customer.getPhone() + ":" + token, JSON.toJSONString(customer), 3, TimeUnit.DAYS);
        return token;
    }

    /**
     * 删除会员缓存Token
     * @param phone
     */
    public void deleteCustomerToken(String phone)
    {
        Collection<String> collection = redisCache.keys(CacheConstants.CUSTOMER_TOKEN + phone + "*");
        if (collection.size() > 0)
        {
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
            }
            redisCache.deleteObject(tokenKey);
        }
    }

    /**
     * 刷新缓存中的会员信息
     * @param customer
     */
    public void refreshCacheCustomer(Customer customer)
    {
        Collection<String> collection = redisCache.keys(CacheConstants.CUSTOMER_TOKEN + customer.getPhone() + "*");
        if (collection.size() > 0)
        {
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
            }
            redisCache.setCacheObject(tokenKey, JSON.toJSONString(customer));
        }
    }
}
